1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package storm.starter.tools;
19  
20  import backtype.storm.tuple.Tuple;
21  import com.google.common.collect.Lists;
22  import org.testng.annotations.DataProvider;
23  import org.testng.annotations.Test;
24  
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import static org.fest.assertions.api.Assertions.assertThat;
29  import static org.mockito.Mockito.*;
30  import static org.testng.Assert.assertFalse;
31  import static org.testng.Assert.assertTrue;
32  
33  public class RankableObjectWithFieldsTest {
34  
35    private static final Object ANY_OBJECT = new Object();
36    private static final long ANY_COUNT = 271;
37    private static final String ANY_FIELD = "someAdditionalField";
38    private static final int GREATER_THAN = 1;
39    private static final int EQUAL_TO = 0;
40    private static final int SMALLER_THAN = -1;
41  
42    @Test(expectedExceptions = IllegalArgumentException.class)
43    public void constructorWithNullObjectAndNoFieldsShouldThrowIAE() {
44      new RankableObjectWithFields(null, ANY_COUNT);
45    }
46  
47    @Test(expectedExceptions = IllegalArgumentException.class)
48    public void constructorWithNullObjectAndFieldsShouldThrowIAE() {
49      Object someAdditionalField = new Object();
50      new RankableObjectWithFields(null, ANY_COUNT, someAdditionalField);
51    }
52  
53    @Test(expectedExceptions = IllegalArgumentException.class)
54    public void constructorWithNegativeCountAndNoFieldsShouldThrowIAE() {
55      new RankableObjectWithFields(ANY_OBJECT, -1);
56    }
57  
58    @Test(expectedExceptions = IllegalArgumentException.class)
59    public void constructorWithNegativeCountAndFieldsShouldThrowIAE() {
60      Object someAdditionalField = new Object();
61      new RankableObjectWithFields(ANY_OBJECT, -1, someAdditionalField);
62    }
63  
64    @Test
65    public void shouldBeEqualToItself() {
66      RankableObjectWithFields r = new RankableObjectWithFields(ANY_OBJECT, ANY_COUNT);
67      assertThat(r).isEqualTo(r);
68    }
69  
70    @DataProvider
71    public Object[][] otherClassesData() {
72      return new Object[][]{ { new String("foo") }, { new Object() }, { Integer.valueOf(4) }, { Lists.newArrayList(7, 8,
73          9) } };
74    }
75  
76    @Test(dataProvider = "otherClassesData")
77    public void shouldNotBeEqualToInstancesOfOtherClasses(Object notARankable) {
78      RankableObjectWithFields r = new RankableObjectWithFields(ANY_OBJECT, ANY_COUNT);
79      assertFalse(r.equals(notARankable), r + " is equal to " + notARankable + " but it should not be");
80    }
81  
82    @DataProvider
83    public Object[][] falseDuplicatesData() {
84      return new Object[][]{ { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 1) },
85          { new RankableObjectWithFields("foo", 1), new RankableObjectWithFields("Foo", 1) },
86          { new RankableObjectWithFields("foo", 1), new RankableObjectWithFields("FOO", 1) },
87          { new RankableObjectWithFields("foo", 1), new RankableObjectWithFields("bar", 1) },
88          { new RankableObjectWithFields("", 0), new RankableObjectWithFields("", 1) }, { new RankableObjectWithFields("",
89          1), new RankableObjectWithFields("bar", 1) } };
90    }
91  
92    @Test(dataProvider = "falseDuplicatesData")
93    public void shouldNotBeEqualToFalseDuplicates(RankableObjectWithFields r, RankableObjectWithFields falseDuplicate) {
94      assertFalse(r.equals(falseDuplicate), r + " is equal to " + falseDuplicate + " but it should not be");
95    }
96  
97    @Test(dataProvider = "falseDuplicatesData")
98    public void shouldHaveDifferentHashCodeThanFalseDuplicates(RankableObjectWithFields r,
99        RankableObjectWithFields falseDuplicate) {
100     assertThat(r.hashCode()).isNotEqualTo(falseDuplicate.hashCode());
101   }
102 
103   @DataProvider
104   public Object[][] trueDuplicatesData() {
105     return new Object[][]{ { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 0) },
106         { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 0, "someOtherField") },
107         { new RankableObjectWithFields("foo", 0, "someField"), new RankableObjectWithFields("foo", 0,
108             "someOtherField") } };
109   }
110 
111   @Test(dataProvider = "trueDuplicatesData")
112   public void shouldBeEqualToTrueDuplicates(RankableObjectWithFields r, RankableObjectWithFields trueDuplicate) {
113     assertTrue(r.equals(trueDuplicate), r + " is not equal to " + trueDuplicate + " but it should be");
114   }
115 
116   @Test(dataProvider = "trueDuplicatesData")
117   public void shouldHaveSameHashCodeAsTrueDuplicates(RankableObjectWithFields r,
118       RankableObjectWithFields trueDuplicate) {
119     assertThat(r.hashCode()).isEqualTo(trueDuplicate.hashCode());
120   }
121 
122   @DataProvider
123   public Object[][] compareToData() {
124     return new Object[][]{ { new RankableObjectWithFields("foo", 1000), new RankableObjectWithFields("foo", 0),
125         GREATER_THAN }, { new RankableObjectWithFields("foo", 1), new RankableObjectWithFields("foo", 0),
126         GREATER_THAN }, { new RankableObjectWithFields("foo", 1000), new RankableObjectWithFields("bar", 0),
127         GREATER_THAN }, { new RankableObjectWithFields("foo", 1), new RankableObjectWithFields("bar", 0),
128         GREATER_THAN }, { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 0), EQUAL_TO },
129         { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("bar", 0), EQUAL_TO },
130         { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 1000), SMALLER_THAN },
131         { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 1), SMALLER_THAN },
132         { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("bar", 1), SMALLER_THAN },
133         { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("bar", 1000), SMALLER_THAN }, };
134   }
135 
136   @Test(dataProvider = "compareToData")
137   public void verifyCompareTo(RankableObjectWithFields first, RankableObjectWithFields second, int expCompareToValue) {
138     assertThat(first.compareTo(second)).isEqualTo(expCompareToValue);
139   }
140 
141   @DataProvider
142   public Object[][] toStringData() {
143     return new Object[][]{ { new String("foo"), 0L }, { new String("BAR"), 8L } };
144   }
145 
146   @Test(dataProvider = "toStringData")
147   public void toStringShouldContainStringRepresentationsOfObjectAndCount(Object obj, long count) {
148     // given
149     RankableObjectWithFields r = new RankableObjectWithFields(obj, count);
150 
151     // when
152     String strRepresentation = r.toString();
153 
154     // then
155     assertThat(strRepresentation).contains(obj.toString()).contains("" + count);
156   }
157 
158   @Test
159   public void shouldReturnTheObject() {
160     // given
161     RankableObjectWithFields r = new RankableObjectWithFields(ANY_OBJECT, ANY_COUNT, ANY_FIELD);
162 
163     // when
164     Object obj = r.getObject();
165 
166     // then
167     assertThat(obj).isEqualTo(ANY_OBJECT);
168   }
169 
170   @Test
171   public void shouldReturnTheCount() {
172     // given
173     RankableObjectWithFields r = new RankableObjectWithFields(ANY_OBJECT, ANY_COUNT, ANY_FIELD);
174 
175     // when
176     long count = r.getCount();
177 
178     // then
179     assertThat(count).isEqualTo(ANY_COUNT);
180   }
181 
182   @DataProvider
183   public Object[][] fieldsData() {
184     return new Object[][]{ { ANY_OBJECT, ANY_COUNT, new Object[]{ ANY_FIELD } },
185         { "quux", 42L, new Object[]{ "one", "two", "three" } } };
186   }
187 
188   @Test(dataProvider = "fieldsData")
189   public void shouldReturnTheFields(Object obj, long count, Object[] fields) {
190     // given
191     RankableObjectWithFields r = new RankableObjectWithFields(obj, count, fields);
192 
193     // when
194     List<Object> actualFields = r.getFields();
195 
196     // then
197     assertThat(actualFields).isEqualTo(Lists.newArrayList(fields));
198   }
199 
200   @Test(expectedExceptions = UnsupportedOperationException.class)
201   public void fieldsShouldBeImmutable() {
202     // given
203     RankableObjectWithFields r = new RankableObjectWithFields(ANY_OBJECT, ANY_COUNT, ANY_FIELD);
204 
205     // when
206     List<Object> fields = r.getFields();
207     // try to modify the list, which should fail
208     fields.remove(0);
209 
210     // then (exception)
211   }
212 
213   @Test
214   public void shouldCreateRankableObjectFromTuple() {
215     // given
216     Tuple tuple = mock(Tuple.class);
217     List<Object> tupleValues = Lists.newArrayList(ANY_OBJECT, ANY_COUNT, ANY_FIELD);
218     when(tuple.getValues()).thenReturn(tupleValues);
219 
220     // when
221     RankableObjectWithFields r = RankableObjectWithFields.from(tuple);
222 
223     // then
224     assertThat(r.getObject()).isEqualTo(ANY_OBJECT);
225     assertThat(r.getCount()).isEqualTo(ANY_COUNT);
226     List<Object> fields = new ArrayList<Object>();
227     fields.add(ANY_FIELD);
228     assertThat(r.getFields()).isEqualTo(fields);
229 
230   }
231 
232   @DataProvider
233   public Object[][] copyData() {
234     return new Object[][]{ { new RankableObjectWithFields("foo", 0) }, { new RankableObjectWithFields("foo", 3,
235         "someOtherField") }, { new RankableObjectWithFields("foo", 0, "someField") } };
236   }
237 
238   // TODO: What would be a good test to ensure that RankableObjectWithFields is at least somewhat defensively copied?
239   //       The contract of Rankable#copy() returns a Rankable value, not a RankableObjectWithFields.
240   @Test(dataProvider = "copyData")
241   public void copyShouldReturnCopy(RankableObjectWithFields original) {
242     // given
243 
244     // when
245     Rankable copy = original.copy();
246 
247     // then
248     assertThat(copy.getObject()).isEqualTo(original.getObject());
249     assertThat(copy.getCount()).isEqualTo(original.getCount());
250   }
251 
252 }